리액트 프로젝트 시작

한동안 리액트 포스팅은 ‘실전 리액트 프로그래밍’ 책을 토대로 리액트의 기본부터 익혀볼까 한다.

요즘 빠르게 발전하는 기술에 프레임워크나 라이브러리의 사용법 보다는 핵심적인 원리를 이해하는 것이 중요하며, 그렇게 하면 새로운 기술이 나오더라도 빠르게 습득이 가능하고, 비판적 사고도 갖출 수 있다.

리액트는 가상 돔 개념을 사용하고, 가상 돔 개념을 이해한다면 앞으로 나올 가상 돔을 적용한 다른 프레임 워크 동작도 쉽게 이해할 수 있다.

목표

  • 가상 돔 개념 이해하기
  • 비판적 사고 갖추기
  • 바벨과 웹팩 이해하기
  • 정적 타입 과 타입스크립트
  • 파이버

리액트란?

페이스북에서 개발하고 관리하는 UI 라이브러리, 앵귤러가 웹 애플리케이션 개발에 필요한 다수의 기능을 제공하는 것과 다르게 리액트는 UI기능만 제공한다. 이 말은 개발자가 UI기능을 제외한건 직접 구축해야한다는 것이다. (전역 상태 관리, 라우팅, 빌드 시스템 등)

UI 기능만 제공하기 때문에 초보자들에게는 진입 장벽이 높은데 이걸 낮추기 위해서 리액트 팀은 create-react-app을 만들었다. create-react-app을 이용하면 눈 깜작할 사이에 리액트 개발 환경을 구축할 수 있다.

리액트를 사용하는 이유 중 하나는 UI를 자동으로 업데이트 해준다는 점 때문이다 대개 프로그맹의 상태가 변하면 UI도 변경해주는데 UI = render(state) 로 함축적으로 표현할 수 있다.

리액트의 장점은 가상 돔(Virtual Dom)을 통해서 UI를 빠르게 업데이트를 한다는 점이다. 만약 리액트를 사용하지 않는다면 브라우저의 돔을 직접 업데이트해야 한다 돔을 직접 업데이트 하는 코드는 잘 관리하지 않으면 프로그램이 커질수록 복잡도가 높아진다.

리액트는 함수형 프로그래밍을 적극적으로 활용하고 리액트에는 제약 사항이 있다.

  1. 렌더 함수는 순수 함수로 작성해야 한다.
  2. 컴포넌트 상대값은 불변 객체로 관리해야 한다.

위 사항에서

  1. render 함수는 순수 함수여야 하므로 인수 state가 변하지 않으면 항상 같은 값을 반환해야 한다.

  2. 컴퍼넌트의 상대값을 수정할 때는 기존 값을 변경하는게 아니라 새로운 객체를 생성해야한다.

코드에 순수 함수불변 객체를 적극적으로 사용하면 복잡도가 낮아지고, 찾기 힘든 버그 발생 확률이 낮아진다. 리액트는 1,2 제약 상황 덕분에 랜더링 성능을 크게 향상할 수 있다.

개발 환경 직접 구축하기

Hello World 페이지 만들기

1) Hello-word라는 파일을 만들고 아래 4개의 파일을 넣어준다

  1. https://unpkg.com/react@16.8.6/umd/react.development.js
  2. https://unpkg.com/react@16.8.6/umd/react.production.min.js
  3. https://unpkg.com/react-dom@16.8.6/umd/react-dom.development.js
  4. https://unpkg.com/react-dom@16.8.6/umd/react-dom.production.min.js

1,3 번 파일은 개발환경에 사용되는 파일이며, 개발 시 도움이 되는 에러 메시지를 확인 할 수 있다. 2,4 번 파일은 배포 환경에서 사용되는 파일이다.

1,2 번 파일은 플랫폼 구분 없이 공통으로 사용되는 리액트의 핵심 기능을 담고 있다. 따라서 웹 뿐만 아니라 리액트 네이티브(react-native)에서도 사용된다. 반대로 3,4 번 파일은 웹에서만 사용 가능하다.

리액트 네이트브에 대해서는 나중에 좀 더 자세히 다뤄보자

2) 바벨 사용해 보기

바벨(babel)은 자바스크립트 코드를 변환해 주는 컴파일러이다. 바벨을 사용하면 최신 자바스크립트 문법을 지원하지 않는 환경에서도 최신 문법을 사용할 수 있다.

ES5 까지만 지원하는 브라우저에서 바벨을 이용하면 ES6문법 또는 최신 자바스크립트 문법 코드도 사용 가능하게 변환해 준다 최신 문법을 사용하고 싶은 프로그래머들에게 인기가 높다.

하지만 최신 문법을 사용할 수 있다는 장점 외에도 다른 장점들도 존재한다. 주석을 제거하거나 코드를 압축하는 용도로 사용 할 수 있다.

리액트는 JSX 문법을 사용하기 위해 버벨을 사용한다. 바벨이 JSX 문법으로 작성된 코드를 createElement 함수를 호출하는 코드로 변환해 준다.

JSX 문법을 바벨로 컴파일하기

JSX는 자바스크립트 표준 문법이 아니다. 그렇기 때문에 바벨을 이용해서 JSX 문법으로 작성된 파일을 createElement 함수로 작성된 파일로 변환해야한다.

npm install @babel/core @babel/cli @babel/preset-react
  • @babel/cli - 커맨드 라인에서 바벨을 실핼할 수 있는 파이너리 파일이 있다.
  • @babel/preset-react - JSX로 작성된 코드를 createElement 함수를 이용한 코드로 변환해 주는 바벨 플러그인

3) 웹팩의 기본 개념 이해

웹팩(webpack)은 자바스크립트로 만든 프로그램을 배포하기 좋은 형태로 묶어주는 툴이다. 여기서 배포하기 좋은 형태 란 최근에 웹 페이지를 단일 페이지 애플리케이션(single page application)으로 전환하다 보니 한 페이지에 수 많은 자바스크립트 파일이 필요로 하게 되었는데 예전 웹 페이지들 보다 많은 양의 파일들을 관리해야하기때문에 웹팩이 이를 손쉽게 관리해준다.

또한 웹팩은 ESM(ES6의 모듈 시스템)과 commonJS를 모두 지원한다. 모듈 시스템을 이용해서 코드를 작성하고 웹팩을 실행하면 예전 버전의 브라우저에서도 동작하는 자바스크립트 코드를 만들 수 있다.

웹팩은 실행을 하면 자바스크립트 파일을 보통은 하나, 원한다면 여러 개의 파일로 분활 가능하다. 개발자가 할 일은 웹팩이 만든 파일을 태그에 포함시키면 될 뿐이다.

import React from 'react';
import ReactDOM from 'react-dom';
import Button from './Button.js';
//ESM 문법을 이용해서 필요한 모듈을 가져오고 있다.

function Container() {
  return React.createElement(
    'div',
    null,
    React.createElement('p', null, '웹팩 사용해 보자'),
    React.createElement(Button, { label: '클래스형' }),
    React.createElement(Button, { label: '함수형' }),
  );
}

위 Container 컴포넌트는 함수형 컴포넌트이다. 기존 클래스형 과는 다르지만 랜더 함수만 필요한 경우네는 함수형 컴포넌트가 좋다.

클래스형 컴포넌트 함수형 컴포넌트

  • 클래스형 컴포넌트

    • 기능적 측면에서 함수형 컴포넌트가 할 수 있는 모든 일을 할 수 있다.
  • 함수형 컴포넌트

    • 리액트 16.8 이전 버전의 함수형 컴포넌트가 할 수 없는 일
    • 상태값을 가질 수 없다
    • 리액트 컴포넌트의 생명 주기 함수를 작성할 수 없다
    • 리액트 버전 16.8부터 훅(Hook)기능 추가 이후 가능한 일
    • 상태값을 가질 수 있다
    • 생명 주기 함수 코드를 작성할 수 있다.

프로젝트를 새롭게 시작한다면 클래스형 컴포넌트를 지향하고 훅과 함께 함수형 컴포넌트를 작성하는게 좋다. 기존 프로젝트 관리라면 클래스형 컴포넌트의 생명 주기 메서드를 잘 이해하고 있어야 한다.

페이스북 내부도 아직 클래스형 컴포넌트로 작성된 코드가 많기 때문에 클래스형은 아직은 지원할 것이다.

create-react-app 시작

create-react-app은 리액트로 웹 어플리케이션을 만들기 위한 환경을 제공한다. 만약 앱에 관심이 있다면 리엑트 네이티브를 사용해야한다.

또 한가지 create-react-app에는 앞에서 다룬 바벨, 웹팩도 포함되어 있다 그 외에도 테스트 시스템, HMR1,ES6 + 문법, css 후처리 등 필수라고 할 수 있는 개발환경을 구축가능하다.

create-react-app을 이용하면 기존 기능을 개선하거나 새로운 기능을 추가했을 때 패키지 버전만 올리면 되지만 개발환경을 직접 구축할 경우 오랜시간이 걸리고 유지보수도 해야 한다.

그리고 어떤 문제를 해결하기 위한 선택지가 여러가지라면 create-react-app에서 가장 합리적인 선택지를 해준다.2

npx create-react-app cra-test

Create-react-app 패키지가 설치되어 있지 않더라도 npx가 자동으로 가져와서 실행한다.

npm install -g create-react-app
create-react-app cra-test

만약 npm버전이 낮아서 실행이 안된다면 위와 같이 입력한다.

실행 후에 npm start를 입력하면 빌드가 끝나면 자동으로 브라우저에서 새 탭에 랜더링된 페이지가 열린다. App.js 파일에 텍스트 부분과 다른 부분(20s -> 2s)들을 바꿔보면 브라우저에서 자동으로 업데이트 된다.

이는 HMR 기능이며 npm start 실행 시 crest-react-app이 로컬 서버를 띄워 주기 때문에 가능한 일이다.

npm start는 개발 모드에서 작동하므로 배포할 때 사용하면 안된다.

create-react-app에서 자동으로 생성한 파일 구조를 살펴보자

cra-test
|- README.md
|- node_modules
|- package.json (2)
|- public (4)
|    |- favicon.ico
|    |- index.html (1)(2)
|-src (3)
   |-App.css
   |-App.js
   |-App.test.js
   |-index.css
   |-index.js (1)(2)(3)
   |-logo.svg
   |-serviceWorker.js
  • (1) - index.html, index.js 파일은 빌드 시 예약된 파일 이름이므로 지우면 안 된다.
  • (2) - index.html, index.js, package.json 파일을 제외한 나머지 파일은 데모 앱을 위한 파일이기 때문에 수정,삭제 해도 상관없다.
  • (3) - index.js로부터 연결모든 자바스크립트 파일과 CSS파일은 src파일 밑에 있어야한다.

    • src 폴더 밖에 있는 파일을 import 키워드를 이용해서 가져오려면 실패한다.
  • (4) - index.html에서 참조하는 파일은 public 폴더 밑에 있어야 한다.

    • public 폴더 밑에 있는 자바스크립트 파일이나 CSS파일을 link 나 script 태그를 이용해서 index.html에 포함 시킬 수 있다.
    • 하지만 위 환경일 경우 자바스크립트 파일이나 CSS파일을 자동 압축하지 못한다. import 키워드를 통해포함해야 자동 압축이 가능하다.
  • 이미지,폰트 파일의 경우 src 폴더 밑에서 import 키워드를 사용해서 포함시키는게 좋으며 웹팩에서 해시값을 이용해서 url을 생성해 주기 때문에 파일의 내용이 변경 되지 않으면 브라우저 캐싱 효과 를 볼 수 있다.

파일을 참조하는 경우 외에도 index.html의 내용을 직접 수정해도 된다. Title 태그에서 제목을 직접 입력하는 경우를 예로 들 수 있다. 하지만 제목을 페이지 별로 다르게 줘야 한다면 문제가 된다. 만약 사내에서 웹사이트라면 react-helmet과 같은 패키지를 사용하면 된다. 반대로 일반 사용자를 위한 사이트라면 검색 엔진 최적화를 해야한다면 문제가 크다. 이 문제는 서버사이드 랜더링에 특화된 넥스트(next.js)를 사용하는게 좋다. 넥스트에 대해서는 추후에 포스팅할 예정이다.


  1. HMR(hot-module-replacement)

  2. 수 많은 패키지들이 쏟아져 나오는 가운데 기존에 가장 좋은 방법이라 선택했던 방법이 새로운 방법으로 대체되는 경우가 있는데 이것이 여러가지 선택지이다. 그리고 새로운 선택지를 고르기까지 각 선택지의 장단점을 공부해야하는데 그러한 시간을 아낄 수 있다.